﻿using System;
using System.Diagnostics;
using System.IO;

namespace MLSharp.Utilities
{
	/// <summary>
	/// A simplified wrapper around <see cref="Process"/> that supports
	/// spawning a process and reading output from it.
	/// </summary>
	public class ProcessWrapper
	{
		/// <summary>
		/// Runs the specified process.
		/// </summary>
		/// <param name="processPath">The path to the process.</param>
		/// <param name="workingDirectory">The working directory.</param>
		/// <param name="arguments">The arguments to pass to the process.</param>
		/// <returns>All the output written to stdout.</returns>
		public static ProcessOutput Run(string processPath, string workingDirectory, string arguments)
		{
			if (!Path.IsPathRooted(processPath))
			{
				processPath = Path.Combine(workingDirectory, processPath);
				processPath = Path.GetFullPath(processPath);
			}

			if (!File.Exists(processPath))
			{
				throw new FileNotFoundException("Specified executable could not be found: " + processPath, processPath);
			}

			ProcessStartInfo startInfo = new ProcessStartInfo(processPath);
			startInfo.RedirectStandardOutput = true;
			startInfo.RedirectStandardError = true;
			startInfo.WorkingDirectory = workingDirectory;
			startInfo.Arguments = arguments;
			//This must be false if you are redirecting input/output
			startInfo.UseShellExecute = false;
			startInfo.CreateNoWindow = true;

			ProcessOutput output = new ProcessOutput();

			using (Process process = Process.Start(startInfo))
			{
				if (process == null)
				{
					throw new NullReferenceException("Unable to create the process!");
				}

				output.StandardOutput = process.StandardOutput.ReadToEnd();

				if (!process.StandardError.EndOfStream)
				{
					output.StandardError = process.StandardError.ReadToEnd();
				}

				process.WaitForExit();
			}

			return output;
		}
	}
}
